#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <string>
#include <iostream>
#include "Common.hpp"

#define GetUmask (IPC_CREAT | IPC_EXCL)
#define CREATOR (IPC_CREAT | IPC_EXCL)
#define USER IPC_CREAT

#define DEFAULT_MODE 0666
#define DEFAULT_PATH "."
#define DEFAULT_PJID 208462
#define DEFAULT_SIZE 1024

class Shared_mem
{
private:
    int Get(int flag)
    {
        int shmId = shmget(_key, _size, flag | DEFAULT_MODE);
        if(shmId == -1)
        {
            ERR_EXIT("shmget");
        }
        return shmId;
    }

    void* Attach(int shmId)
    {
        void* tmp = shmat(shmId, nullptr, 0);
        if(tmp == (void*)-1)
        {
            ERR_EXIT("shmat");
        }
        return tmp;
    }
public:
    Shared_mem(key_t key, size_t size, int operType)
        :_key(key)
        , _size(size)
        , _operType(operType)
    {
        std::cout << "正在获取共享内存......" << std::endl;
        _shmId = Get(operType & GetUmask);
        std::cout << "正在将共享内存映射到虚拟地址......" << std::endl;
        _shmAddr = Attach(_shmId);
    }

    size_t Size()
    {
        return _size;
    }
    
    key_t Key()
    {
        return _key;
    }

    int Id()
    {
        return _shmId;
    }

    void* Begin()
    {
        return _shmAddr;
    }

    ~Shared_mem()
    {
        std::cout << "正在解除到共享内存的映射......" << std::endl;
        shmdt(_shmAddr);
        if(_operType == CREATOR)
        {
            std::cout << "正在销毁共享内存......" << std::endl;
            shmctl(_shmId, IPC_RMID, nullptr);
        }
    }
private:
    key_t _key;
    size_t _size;
    int _shmId;
    void* _shmAddr;
    int _operType;
};